'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var app = angular.module("myApp", ['ui.bootstrap', 'ui.bootstrap.treeview2', 'ui.select2']);

var treeViewTemplate = '\n<tree-view ng-if="graphTree != null && graphTree.g != null" tree-service="graphTree" node-label="text"></tree-view>\n';

app.controller("manageController", ['$scope', '$compile', '$filter', '$uibModal', function ($scope, $compile, $filter, $uibModal) {
    $scope.query = {
        fault: FaultNode.faults[0]
    };

    $scope.faultModules = [];

    $scope.component_ref = null;

    $scope.toJSON = function (val) {
        return angular.toJson(val, true);
    };

    // $scope.faults=FaultNode.faults;
    FaultNode.loadFaults.callbacks.push(function () {
        $scope.faults = FaultNode.faults;
        $scope.$apply();
    });
    FaultNode.loadFaults.callbacks.push(function () {
        $scope.query.fault = FaultNode.faults[0];
        $scope.$apply();
    });
    FaultNode.loadFaults();

    $scope.components = ComponentNode.components;
    ComponentNode.loadComponents.callbacks.push(function () {
        return $scope.components = ComponentNode.components;
    });
    ComponentNode.loadComponents();

    // $scope.graphTree = new TreeView();
    $scope.graphTree = new NodeTreeView();
    $scope.$watch('query', function (newValue, oldValue) {
        console.info($scope.query);
        // if ($scope.updated){
        //     if (!confirm('您已修改了当前故障，是否放弃当前修改内容？')){
        //         $scope.query = oldValue;
        //     }else {
        //         $scope.updated = false;
        //     }
        // }
        if ($scope.query.fault) Graph.loadGraph($scope.query.fault.id, function (g) {
            $scope.reloadGraph(g);
        });
    }, true);

    $scope.refacteGraph = function () {
        var root = $scope.graph.getRoot();
        var features = [].concat(_toConsumableArray($scope.graph.nodes.values())).filter(function (x) {
            return x.$type == 'Feature';
        });

        var andFunction = function andFunction(xl, yl) {
            var flist = [];
            for (var _i = 0; _i < xl.length; _i++) {
                var x = xl[_i];
                inner_for: for (var j = 0; j < yl.length; j++) {
                    var y = yl[j];
                    var fs = [];
                    for (var k = 0; k < features.length; k++) {
                        if (x[k] == -1) {
                            fs[k] = y[k];
                        } else if (y[k] == -1) {
                            fs[k] = x[k];
                        } else if (x[k] == y[k]) {
                            fs[k] = x[k];
                        } else {
                            //存在冲突，无结果
                            continue inner_for;
                        }
                    }
                    flist.push(fs);
                }
            }

            return flist;
        };

        function split(terms, i) {
            if (i >= features.length) return terms;
            return terms.map(function (term) {
                if (term[i] == -1) {
                    var s1 = [].concat(_toConsumableArray(term));
                    var s2 = [].concat(_toConsumableArray(term));
                    s1[i] = 0;
                    s2[i] = 1;
                    return [].concat(_toConsumableArray(split([s1], i + 1)), _toConsumableArray(split([s2], i + 1)));
                } else {
                    return [].concat(_toConsumableArray(split([term], i + 1)));
                }
            }).reduce(function (l1, l2) {
                return [].concat(_toConsumableArray(l1), _toConsumableArray(l2));
            });
        }

        function calculate(node) {
            if (node.$type == 'Feature') {
                var index = features.indexOf(node);
                var fs = Array.from({ length: features.length }, function (_, index) {
                    return -1;
                });
                fs[index] = 1;
                // console.info("Feature",node.id,fs);
                return [fs];
            } else if (node.$type == 'FeatureGroup' && node.combineType == 'not') {
                //not 只有第一个元素有效
                var list = $scope.graph.edges.filter(function (edgs) {
                    return edgs.from == node.id;
                }).map(function (edge) {
                    return $scope.graph.getNode(edge.to);
                }).filter(function (n) {
                    return _.startsWith(n.$type, 'Feature');
                });
                if (list.length > 0) {
                    var f = list[0];
                    var _fs = calculate(f);
                    var _terms = split(_fs, 0);
                    return _terms.map(function (term) {
                        return term.map(function (i) {
                            if (i == 0) return 1;
                            if (i == 1) return 0;
                            return i;
                        });
                    }).reduce(andFunction);
                } else {
                    return [];
                }
            } else if (node.$type == 'FeatureGroup' && node.combineType == 'and') {
                var _list = $scope.graph.edges.filter(function (edgs) {
                    return edgs.from == node.id;
                }).map(function (edge) {
                    return $scope.graph.getNode(edge.to);
                }).filter(function (n) {
                    return _.startsWith(n.$type, 'Feature');
                }).map(function (n) {
                    return calculate(n);
                });
                _list = _list.reduce(andFunction);

                // console.info(node.$type,node.id,list);
                return _list;
            } else {
                //or Fault也视为or
                var _list2 = $scope.graph.edges.filter(function (edgs) {
                    return edgs.from == node.id;
                }).map(function (edge) {
                    return $scope.graph.getNode(edge.to);
                }).filter(function (n) {
                    return _.startsWith(n.$type, 'Feature');
                }).map(function (n) {
                    return calculate(n);
                }).reduce(function (x, y) {
                    return [].concat(x).concat(y);
                });
                // console.info(node.$type,node.id,list);
                return _list2;
            }
        }

        var miniterms = calculate(root);

        var terms = split(miniterms, 0);
        var min2 = terms.map(function (t) {
            var m = new Minterm(features.length);
            m.mins = t;
            return m;
        });
        var var_count = features.length;

        var total = new HashSet();
        var i = 0;
        do {
            var covered = Minterm.cover(Minterm.qm(min2, var_count), min2, var_count);
            var _iteratorNormalCompletion = true;
            var _didIteratorError = false;
            var _iteratorError = undefined;

            try {
                for (var _iterator = covered[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                    var e = _step.value;

                    total.add(e);
                }
            } catch (err) {
                _didIteratorError = true;
                _iteratorError = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion && _iterator.return) {
                        _iterator.return();
                    }
                } finally {
                    if (_didIteratorError) {
                        throw _iteratorError;
                    }
                }
            }

            var _loop = function _loop(cov) {
                min2 = _.remove(min2, function (v) {
                    return cov.cover(v);
                });
                // min2.removeIf(cov::cover);
            };

            var _iteratorNormalCompletion2 = true;
            var _didIteratorError2 = false;
            var _iteratorError2 = undefined;

            try {
                for (var _iterator2 = covered[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                    var cov = _step2.value;

                    _loop(cov);
                }
            } catch (err) {
                _didIteratorError2 = true;
                _iteratorError2 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion2 && _iterator2.return) {
                        _iterator2.return();
                    }
                } finally {
                    if (_didIteratorError2) {
                        throw _iteratorError2;
                    }
                }
            }

            i++;
        } while (min2.size() > 0 && i <= 1);

        var finalResult = total.toArray().map(function (group) {
            return {
                type: "and",
                children: group.mins.map(function (val, index) {
                    if (val == -1) {
                        return {
                            type: "any"
                        };
                    } else if (val == 0) {
                        return {
                            type: "not",
                            id: features[index].id,
                            name: features[index].name
                        };
                    } else {
                        return {
                            type: "feature",
                            id: features[index].id,
                            name: features[index].name
                        };
                    }
                }).filter(function (x) {
                    return x.type != 'any';
                })
            };
        });

        if (features.length > 1) {
            (function () {
                var featureGroups = [].concat(_toConsumableArray($scope.graph.nodes.values())).filter(function (x) {
                    return x.$type == 'FeatureGroup';
                });
                var featureTypes = [].concat(_toConsumableArray(features), _toConsumableArray(featureGroups));

                $scope.graph.edges.filter(function (edge) {
                    return featureTypes.some(function (n) {
                        return n.id == edge.to;
                    });
                }).forEach(function (edge) {
                    return edge.$removed = true;
                });
                featureGroups.every(function (fg) {
                    return fg.$removed = true;
                });

                var g = $scope.graph;
                var newRoot = new GroupNode('Feature');
                var newAndGroups = finalResult.map(function (x) {
                    return new GroupNode('Feature', 'new', { combineType: 'and' });
                });
                // newAndGroups.forEach(n=>n.combineType='and');
                g.addNode(newRoot);
                newAndGroups.forEach(function (n) {
                    return g.addNode(n);
                });
                g.addLink(root.id, newRoot.id);
                newAndGroups.forEach(function (n) {
                    return g.addLink(newRoot.id, n.id);
                });

                finalResult.forEach(function (andGroup, index) {
                    andGroup.children.forEach(function (child) {
                        if (child.type == 'feature') {
                            g.addLink(newAndGroups[index].id, child.id);
                        } else if (child.type == 'not') {
                            var notNode = new GroupNode("Feature", { combineType: 'not' });
                            notNode.combineType = 'not';
                            g.addNode(notNode);
                            g.addLink(newAndGroups[index].id, notNode.id);
                            g.addLink(notNode.id, child.id);
                        }
                    });
                });

                //查找只有一个子节点的Group,移除之
                var count = 0;
                do {
                    var tobeRemoved = newAndGroups.filter(function (x) {
                        return !x.$removed && g.edges.filter(function (edge) {
                            return !edge.$removed && edge.from == x.id;
                        }).length <= 1;
                    });
                    count = tobeRemoved.length;
                    tobeRemoved.forEach(function (x) {
                        g.edges.filter(function (edge) {
                            return edge.from == newRoot.id && edge.to == x.id;
                        }).forEach(function (edge) {
                            return edge.$removed = true;
                        });
                        g.edges.filter(function (edge) {
                            return edge.from == x.id;
                        }).forEach(function (edge) {
                            return edge.from = newRoot.id;
                        });
                        x.$removed = true;
                    });
                } while (count > 0);
                var rootSubs = g.edges.filter(function (edge) {
                    return !edge.$removed && edge.from == newRoot.id;
                });
                if (rootSubs.length <= 1) {
                    g.edges.filter(function (edge) {
                        return edge.from == root.id && edge.to == newRoot.id;
                    }).forEach(function (edge) {
                        return edge.$removed = true;
                    });
                    g.edges.filter(function (edge) {
                        return edge.from == newRoot.id;
                    }).forEach(function (edge) {
                        return edge.from = root.id;
                    });
                    newRoot.$removed = true;
                }
            })();
        }

        $scope.reloadGraph($scope.graph);
        // const modalInstance = $uibModal.open({
        //     template: `<div>原始内容为：${angular.toJson(miniterms)}</div><div>展开为：${angular.toJson(terms)}</div><div>重构结果为：${angular.toJson(total.toArray())}</div><div>最终结果为：${angular.toJson(finalResult)}</div>`,
        //     animation: true,
        //     size: 'lg'
        // });
    };

    $scope.updated = false;
    $scope.$watch('graph.nodes', function () {
        $scope.updated = true;
    });

    $scope.$watch('graphTree.selectedNode', function () {
        var node = $scope.graphTree.selectedNode;
        if ($scope.graph && !!node) {
            var template = node.getTemplate($scope.graphTree.fromEdge, $scope.graph);
            var tp = $compile(template)($scope);
            angular.element("#nodeDetail2").html("").append(tp);
        }
    }, true);

    $scope.filterOfFault = function (fault) {
        if ($scope.query.faultType && $scope.query.faultType != '') {
            if (fault.faultCategory != $scope.query.faultType) {
                return false;
            }
        }
        if ($scope.query.faultModule && $scope.query.faultModule != '') {
            if (fault.faultModule != $scope.query.faultModule) {
                return false;
            }
        }
        return true;
    };

    $scope.frequencyUpdated = function (id) {
        var fg = $scope.graph.getNode(id);
        var root = $scope.graph.getRoot().id;
        if (fg.frequency[root] < 0) {
            fg.frequency[root] = 0;
        } else {
            var sum = Object.values(fg.frequency).reduce(function (x, y) {
                return eval(x) + eval(y);
            }, 0);
            if (sum > eval(fg.quantum)) {
                if (confirm("分配的数量超过可分配的范围，是否扩充总量？")) {
                    fg.quantum = sum;
                } else {
                    var little = eval(fg.quantum) - sum + eval(fg.frequency[root]);
                    fg.frequency[root] = little > 0 ? little : 0;
                }
            }
        }
    };

    $scope.createNewGraph = function () {
        var g = new Graph();
        var fault = new FaultNode();
        g.addNode(fault);

        angular.element("#nodeDetail2").html("");
        angular.element("#treeDiv").html("");
        delete $scope.graph;
        delete $scope.graphTree;
        $scope.graph = g;
        $scope.graphTree = new NodeTreeView();
        $scope.graphTree.g = g;
        $scope.graphTree.collapseAll();
        var tp = $compile(treeViewTemplate)($scope);
        angular.element("#treeDiv").html("").append(tp);
        // $scope.reloadGraph(g);
    };

    $scope.reloadGraph = function (g) {
        var session = neo4jService.getSession();
        g.markSubGraph().then(function () {
            return Promise.all([].concat(_toConsumableArray(g.nodes.values())).filter(function (n) {
                return n.$is_sub_graph && !n.$removed;
            }).map(function (n) {
                return new Promise(function (resolve, reject) {
                    return MyNode.getAncestors(session, n.id).then(function (nd) {
                        nd.filter(function (ndd) {
                            return ndd.$type == "Fault";
                        }).forEach(function (nddx) {
                            n.$faults = n.$faults || new Set();
                            n.$faults.add(nddx);
                        });
                        resolve();
                    });
                });
            }));
        }).then(function () {
            return g.markSubGraph2();
        }).then(function () {
            $scope.$apply(function () {
                angular.element("#nodeDetail2").html("");
                angular.element("#treeDiv").html("");
                delete $scope.graph;
                delete $scope.graphTree;
                $scope.graph = g;
                $scope.graphTree = new NodeTreeView();
                $scope.graphTree.g = g;
                $scope.graphTree.collapseAll();
                $scope.updated = true;
                console.info($scope.graphTree);

                var tp = $compile(treeViewTemplate)($scope);
                angular.element("#treeDiv").html("").append(tp);
            });
        });
    };

    $scope.refreshModules = function () {
        getCache("fault_module", function (val) {
            $scope.faultModules = val.map(function (x) {
                if (x.indexOf(':') < 0) {
                    return {
                        category: '',
                        name: x
                    };
                }
                var arr = x.split(':', 2);
                return {
                    category: arr[0],
                    name: arr[1]
                };
            });
            $scope.faultModules.splice(0, 0, '');
        }, function (callback, cache, name) {
            getConfigure('module', function (data) {
                cache[name] = {
                    lastTimestamp: new Date().getTime(),
                    value: data
                };
                callback(data);
            });
        }, 5000);
    };
    $scope.refreshModules();

    $scope.refreshFaults = function () {
        FaultNode.loadFaults.callbacks = [function () {
            return $scope.faults = FaultNode.faults;
        }];
        FaultNode.loadFaults();

        ComponentNode.loadComponents();

        $scope.refreshModules();
    };

    $scope.allowFeature = function (index) {
        var node = $scope.graph.getNode(index);
        if (!node) {
            return false;
        }

        if (node.$type == 'FeatureGroup') {
            return true;
        } else if (node.$type == 'Fault' || node.$type == 'Reason') {
            var _iteratorNormalCompletion3 = true;
            var _didIteratorError3 = false;
            var _iteratorError3 = undefined;

            try {
                for (var _iterator3 = testEmptyArray(node.list)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                    var nd = _step3.value;

                    if (nd.$type == 'FeatureGroup' || nd.type == 'Feature') {
                        return false;
                    }
                }
            } catch (err) {
                _didIteratorError3 = true;
                _iteratorError3 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion3 && _iterator3.return) {
                        _iterator3.return();
                    }
                } finally {
                    if (_didIteratorError3) {
                        throw _iteratorError3;
                    }
                }
            }

            return true;
        }
        return false;
    };

    $scope.allowCause = function (index) {
        var node = $scope.graph.getNode(index);
        if (!node) {
            return false;
        }
        if (node.$type == 'ReasonGroup') {
            return true;
        } else if (node.$type == 'Fault') {
            var _iteratorNormalCompletion4 = true;
            var _didIteratorError4 = false;
            var _iteratorError4 = undefined;

            try {
                for (var _iterator4 = testEmptyArray(node.list)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
                    var nd = _step4.value;

                    if (nd.$type == 'ReasonGroup' || nd.$type == 'Reason') {
                        return false;
                    }
                }
            } catch (err) {
                _didIteratorError4 = true;
                _iteratorError4 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion4 && _iterator4.return) {
                        _iterator4.return();
                    }
                } finally {
                    if (_didIteratorError4) {
                        throw _iteratorError4;
                    }
                }
            }

            return true;
        }
        return false;
    };

    $scope.allowComponent = function (index) {
        var node = $scope.graph.getNode(index);
        if (!node) {
            return false;
        }
        if (node.$type == 'ComponentGroup') {
            return true;
        } else if (node.$type == 'Reason' || node.$type == 'Feature') {
            var _iteratorNormalCompletion5 = true;
            var _didIteratorError5 = false;
            var _iteratorError5 = undefined;

            try {
                for (var _iterator5 = testEmptyArray(node.list)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
                    var nd = _step5.value;

                    if (nd.$type == 'ComponentGroup' || nd.$type == 'Component') {
                        return false;
                    }
                }
            } catch (err) {
                _didIteratorError5 = true;
                _iteratorError5 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion5 && _iterator5.return) {
                        _iterator5.return();
                    }
                } finally {
                    if (_didIteratorError5) {
                        throw _iteratorError5;
                    }
                }
            }

            return true;
        }
        return false;
    };

    $scope.attachNode = function (type, id) {
        var node = void 0;
        switch (type) {
            case 'Fault':
                node = new FaultNode();
                break;
            case 'Feature':
                node = new FeatureNode();
                break;
            case 'Reason':
                node = new ReasonNode();
                break;
            case 'Component':
                node = new ComponentNode();
                break;
            case 'MatchFunction':
                node = new MatchFunctionNode();
                break;
            case 'FeatureGroup':
                node = new GroupNode('Feature');
                break;
            case 'ReasonGroup':
                node = new GroupNode('Reason');
                break;
            case 'ComponentGroup':
                node = new GroupNode('Component');
                break;
            default:
        }
        var edge = new Edge($scope.graph, id, node.id);
        $scope.graph.addNode(node);
        $scope.graph.edges.push(edge);
        // $scope.graphTree.nodes = [$scope.graph.toJsonTree()];
        // $scope.graphTree.collapseAll();
    };

    $scope.attachExternalNode = function (type, id) {
        var extrnal_id = prompt('\u8BF7\u8F93\u5165\u4E00\u4E2A' + type + '\u7C7B\u578B\u7684\u5916\u90E8\u8282\u70B9ID,\u5EFA\u8BAE\u5728\u53E6\u4E00\u4E2A\u6807\u7B7E\u9875\u4E2D\u67E5\u770B\uFF1A');

        var session = neo4jService.getSession();
        var resultPromise = session.run('start n=node(' + extrnal_id + ') RETURN n');
        resultPromise.then(function (result) {
            session.close();
            result.records.map(function (record) {
                return record.get(0);
            }).map(function (node) {
                return MyNode.fromNeo4jNode(node);
            }).forEach(function (extrnal_node) {
                //验证外部节点的类型，并添加到图中
                if (extrnal_node.$type == type) {
                    Graph.loadGraph(extrnal_id, function (g) {
                        $scope.graph.nodes = new Map([].concat(_toConsumableArray($scope.graph.nodes), _toConsumableArray(g.nodes)));
                        $scope.graph.edges = $scope.graph.edges.concat(g.edges);
                        var edge = new Edge($scope.graph, id, extrnal_id);
                        $scope.graph.edges.push(edge);
                        $scope.$apply();
                    });
                } else {
                    alert(extrnal_id + '\u4E0D\u662F' + type + '\u7C7B\u578B\u7684\u8282\u70B9\uFF0C\u65E0\u6CD5\u6DFB\u52A0\u3002');
                }
            });
        }).catch(function (e) {
            alert('\u6DFB\u52A0' + extrnal_id + '\u5931\u8D25\uFF0C\u539F\u56E0\u662F' + e);
        });
    };

    $scope.attachFeature = function (id) {
        return $scope.attachNode('Feature', id);
    };
    $scope.attachReason = function (id) {
        return $scope.attachNode('Reason', id);
    };
    $scope.attachComponent = function (index) {
        var cp = ComponentNode.components.filter(function (nd) {
            var _iteratorNormalCompletion6 = true;
            var _didIteratorError6 = false;
            var _iteratorError6 = undefined;

            try {
                for (var _iterator6 = $scope.graph.edges[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
                    var eg = _step6.value;

                    if (eg.from == index && eg.to == nd.id) return false;
                }
            } catch (err) {
                _didIteratorError6 = true;
                _iteratorError6 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion6 && _iterator6.return) {
                        _iterator6.return();
                    }
                } finally {
                    if (_didIteratorError6) {
                        throw _iteratorError6;
                    }
                }
            }

            return true;
        })[0];
        if (!cp) {
            alert('请补充元件列表！');
            return;
        }
        // let edge = new Edge($scope.graph,index,cp.id);
        $scope.graph.addNode(cp);
        // $scope.graph.edges.push(edge);
        $scope.graph.addLink(index, cp.id);
        // $scope.graphTree.nodes = [$scope.graph.toJsonTree()];
        // $scope.graphTree.collapseAll();
    };

    $scope.attachGroup = function (index, groupType) {
        return $scope.attachNode(groupType, index);
    };

    $scope.attachExternalFeature = function (id) {
        return $scope.attachExternalNode('Feature', id);
    };
    $scope.attachExternalGroup = function (index, groupType) {
        return $scope.attachExternalNode(groupType, index);
    };

    $scope.appendArgv = function (index) {
        $scope.graph.getNode(index).params.push(0);
    };

    $scope.removeArgv = function (index, position) {
        $scope.graph.getNode(index).params.splice(position, 1);
    };

    $scope.removeEdge = function (edgeId) {
        var edge = $scope.graph.getLink(edgeId);
        for (var i = 0; i < $scope.graph.edges.length; i++) {
            var eg = $scope.graph.edges[i];
            if (!eg.$removed && eg.from == edge.from && eg.to == edge.to) {
                $scope.graph.edges[i].$removed = true;
            }
        }
        // $scope.graphTree.nodes = [$scope.graph.toJsonTree()];
        // $scope.graphTree.collapseAll();
    };

    $scope.persistGraph = function () {
        $scope.graph.persist(function (r) {
            $scope.updated = false;
            alert("数据库同步成功！");
        }, function (e) {
            return console.error(e);
        });
    };

    $scope.persistGraphClone = function () {
        $scope.graph.persistClone(function (r) {
            return alert("复制成功！");
        }, function (e) {
            return console.error(e);
        });
    };

    $scope.deleteFault = function () {
        if (confirm('确认删除故障' + $scope.graph.getRoot()["name"])) $scope.graph.removeFromDB(function () {
            return alert("删除成功！");
        });
    };

    $scope.sortByOutId = function (f) {
        if (!f.outId) {
            return 0;
        }
        return parseInt(f.outId, 10);
    };

    // $scope.sortByEdgeId = function (edge) {
    //     return edge.id;
    // };

    $scope.nextFaults = function () {
        var currentFaults = $filter('filter')($scope.faults, { faultCategory: $scope.query.faultType });
        var currentOrdered = $filter('orderBy')(currentFaults, $scope.sortByOutId);
        var index = currentOrdered.indexOf($scope.query.fault);
        if (index < currentOrdered.length - 1) $scope.query.fault = currentOrdered[index + 1];
    };

    $scope.exportFaultAsJson = function () {
        var modalInstance = $uibModal.open({
            template: '<div>' + angular.toJson($scope.graph.toJson()) + '</div>',
            animation: true,
            size: 'lg'
        });
        // 更新页面内容
        // modalInstance.result.then(function(response) {
        // refreshByCloseStatus(response, $scope.vehicles);
        // });
    };
}]);

// const TRUE = first => second => first;
// const FALSE = first => second => second;
//
//
// const toBoolean = boolFn => boolFn(true)(false);
// const fromBoolean = bool => bool ? TRUE : FALSE;
//
// const not = boolFn => first => second => boolFn(second)(first);
// const or = first => second => first(first)(second);
// const and = first => second => first(second)(first);

var HashSet = function () {
    function HashSet() {
        _classCallCheck(this, HashSet);

        this.map = new Map();
    }

    _createClass(HashSet, [{
        key: 'add',
        value: function add(e) {
            this.map.set(e.hashCode(), e);
        }
    }, {
        key: 'toArray',
        value: function toArray() {
            return [].concat(_toConsumableArray(this.map.values()));
        }
    }, {
        key: 'size',
        value: function size() {
            return this.map.size;
        }
    }]);

    return HashSet;
}();

var Minterm = function () {
    function Minterm(var_count) {
        _classCallCheck(this, Minterm);

        this.mins = Array.from({ length: var_count }, function (_, index) {
            return 0;
        });
        this.num = 0;
        this.flag1 = 0;
        this.flag2 = 0;
    }

    _createClass(Minterm, [{
        key: 'trueCount',
        value: function trueCount() {
            return this.mins.filter(function (x) {
                return x > 0;
            }).length;
        }
    }, {
        key: 'hashCode',
        value: function hashCode() {
            var a = this.mins;
            if (a == null) return 0;

            var result = 1;
            var _iteratorNormalCompletion7 = true;
            var _didIteratorError7 = false;
            var _iteratorError7 = undefined;

            try {
                for (var _iterator7 = a[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
                    var element = _step7.value;

                    result = 31 * result + element;
                }
            } catch (err) {
                _didIteratorError7 = true;
                _iteratorError7 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion7 && _iterator7.return) {
                        _iterator7.return();
                    }
                } finally {
                    if (_didIteratorError7) {
                        throw _iteratorError7;
                    }
                }
            }

            return result;
        }
    }, {
        key: 'equals',
        value: function equals(o) {
            if (this == o) return true;
            if (!(o instanceof Minterm)) return false;

            return this.mins.every(function (val, index) {
                return o.mins[index] === val;
            });
        }

        //比较得出两最小项是否可以合并[即两者的二进制序列只有一位不同，且分别为0、1],返回第几个位置可以合并,-1代表不可合并

    }, {
        key: 'comparison',
        value: function comparison(minterm) {
            var count = 0;
            var flag = -1;
            for (var i = 0; i < this.mins.length; i++) {
                if (this.mins[i] == minterm.mins[i]) {
                    continue;
                } else if (this.mins[i] == -1 && minterm.mins[i] != -1 || this.mins[i] != -1 && minterm.mins[i] == -1) {
                    return -1;
                } else if (this.mins[i] != minterm.mins[i]) {
                    count++;
                    flag = i;
                }
            }
            if (count == 1) {
                return flag;
            } else {
                return -1;
            }
        }
    }, {
        key: 'cover',
        value: function cover(minterm) {
            for (var i = 0; i < this.mins.length; i++) {
                if (this.mins[i] != -1 && this.mins[i] != minterm.mins[i]) {
                    return false;
                }
            }
            return true;
        }
    }], [{
        key: 'qm',
        value: function qm(minterms, var_count) {
            var minlists = [];
            var vec = new HashSet();

            //将最小项按含1的个数分类，用链表保存。
            var _iteratorNormalCompletion8 = true;
            var _didIteratorError8 = false;
            var _iteratorError8 = undefined;

            try {
                for (var _iterator8 = minterms[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
                    var minterm = _step8.value;

                    for (var _j = 0; _j < var_count + 1; _j++) {
                        if (minterm.trueCount() == _j) {
                            if (minlists[_j] == null) {
                                minlists[_j] = new HashSet();
                            }
                            minlists[_j].add(minterm);
                        }
                    }
                }

                //合并最小项
            } catch (err) {
                _didIteratorError8 = true;
                _iteratorError8 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion8 && _iterator8.return) {
                        _iterator8.return();
                    }
                } finally {
                    if (_didIteratorError8) {
                        throw _iteratorError8;
                    }
                }
            }

            while (true) {
                var templist = [];

                for (var i = 0; i < var_count; i++) {
                    var plist = minlists[i],
                        qlist = void 0;
                    if (plist != null) {
                        var _iteratorNormalCompletion9 = true;
                        var _didIteratorError9 = false;
                        var _iteratorError9 = undefined;

                        try {
                            for (var _iterator9 = plist.toArray()[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
                                var p = _step9.value;

                                //                    System.out.println("当前的p:"+p);
                                qlist = minlists[i + 1];
                                if (qlist != null) {
                                    var _iteratorNormalCompletion10 = true;
                                    var _didIteratorError10 = false;
                                    var _iteratorError10 = undefined;

                                    try {
                                        for (var _iterator10 = qlist.toArray()[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
                                            var q = _step10.value;

                                            //判断p,q是否可合并
                                            var c = p.comparison(q);
                                            if (c != -1) {
                                                p.flag2 = 1;
                                                q.flag2 = 1;
                                                var result = new Minterm(var_count);
                                                for (var j = 0; j < var_count; j++) {
                                                    //将合并的结果保存
                                                    if (j != c) {
                                                        result.mins[j] = q.mins[j];
                                                    } else {
                                                        result.mins[j] = -1;
                                                    }
                                                }
                                                //                            System.out.println(""+p+"与"+q+"合并为："+result);
                                                if (templist[i] == null) {
                                                    templist[i] = [];
                                                }
                                                templist[i].add(result);
                                            }
                                        }
                                    } catch (err) {
                                        _didIteratorError10 = true;
                                        _iteratorError10 = err;
                                    } finally {
                                        try {
                                            if (!_iteratorNormalCompletion10 && _iterator10.return) {
                                                _iterator10.return();
                                            }
                                        } finally {
                                            if (_didIteratorError10) {
                                                throw _iteratorError10;
                                            }
                                        }
                                    }
                                } //若p->flag!=1说明p已不可被合并，为本原蕴含项，保存至vec
                                if (p.flag2 != 1) {
                                    //                        System.out.println("p无法被合并："+p);
                                    p.flag2 = -1;
                                    vec.add(p);
                                }
                            }
                        } catch (err) {
                            _didIteratorError9 = true;
                            _iteratorError9 = err;
                        } finally {
                            try {
                                if (!_iteratorNormalCompletion9 && _iterator9.return) {
                                    _iterator9.return();
                                }
                            } finally {
                                if (_didIteratorError9) {
                                    throw _iteratorError9;
                                }
                            }
                        }
                    } //处理未照顾到的最后一项
                    if (i == var_count - 1 && templist[var_count] != null) {
                        var _iteratorNormalCompletion11 = true;
                        var _didIteratorError11 = false;
                        var _iteratorError11 = undefined;

                        try {
                            for (var _iterator11 = templist[var_count][Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
                                var _p = _step11.value;

                                if (_p.flag2 == 0) {
                                    _p.flag2 = -1;
                                    vec.add(_p);
                                }
                            }
                        } catch (err) {
                            _didIteratorError11 = true;
                            _iteratorError11 = err;
                        } finally {
                            try {
                                if (!_iteratorNormalCompletion11 && _iterator11.return) {
                                    _iterator11.return();
                                }
                            } finally {
                                if (_didIteratorError11) {
                                    throw _iteratorError11;
                                }
                            }
                        }
                    }
                }

                //            System.out.println("At 77:");
                //            System.out.println(vec);
                //            System.out.println(Arrays.toString(minlists));
                //            System.out.println(Arrays.toString(templist));

                var f1 = false;
                for (var _i2 = 0; _i2 <= var_count; _i2++) {
                    var k = minlists[_i2];
                    if (k == null) continue;
                    f1 = k.toArray().some(function (m) {
                        return m.flag2 == 1;
                    });
                }
                if (!f1) {
                    var _iteratorNormalCompletion12 = true;
                    var _didIteratorError12 = false;
                    var _iteratorError12 = undefined;

                    try {
                        for (var _iterator12 = templist[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
                            var list = _step12.value;

                            if (list != null) {
                                var _iteratorNormalCompletion13 = true;
                                var _didIteratorError13 = false;
                                var _iteratorError13 = undefined;

                                try {
                                    for (var _iterator13 = new Set(list)[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
                                        var temp = _step13.value;

                                        if (temp != null) {
                                            vec.add(temp);
                                        }
                                    }
                                } catch (err) {
                                    _didIteratorError13 = true;
                                    _iteratorError13 = err;
                                } finally {
                                    try {
                                        if (!_iteratorNormalCompletion13 && _iterator13.return) {
                                            _iterator13.return();
                                        }
                                    } finally {
                                        if (_didIteratorError13) {
                                            throw _iteratorError13;
                                        }
                                    }
                                }
                            }
                        }
                    } catch (err) {
                        _didIteratorError12 = true;
                        _iteratorError12 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion12 && _iterator12.return) {
                                _iterator12.return();
                            }
                        } finally {
                            if (_didIteratorError12) {
                                throw _iteratorError12;
                            }
                        }
                    }

                    break;
                } else {
                    //                for(int i=0;i<=var_count;i++) {
                    //                    f1=false;
                    minlists = templist;
                    // System.arraycopy(templist,0,minlists,0,templist.length);
                    //                }
                }
            }

            //输出找出的本原蕴含项：
            //         console.info("本原蕴含项：");
            //         for (let p of vec.toArray()) {
            //             for(let j=0;j<var_count;j++) {
            //                 if(p.mins[j]!=-1){
            //                     console.info(p.mins[j]);
            //                 }
            //                 else {
            //                     console.info("_");
            //                 }
            //             }
            //         }

            return vec.toArray();
        }
        //寻找最小覆盖

    }, {
        key: 'cover',
        value: function cover(vec, minterms, var_count) {
            var pic = Array.from({ length: vec.length }, function (_, index) {
                return Array.from({ length: minterms.length }, function (_, index) {
                    return 0;
                });
            }); //pic二维数组标志某最小项是否被得出的本原蕴含项表示
            var c1 = Array.from({ length: minterms.length }, function (_, index) {
                return 0;
            }); //用c1数组保存每个最小项被覆盖的次数

            //为pic数组赋值
            var vecList = vec.sort(function (m1, m2) {
                var x1 = m1.mins.reduce(function (x, y) {
                    return x * (y < 0 ? 2 : 1);
                }, -1);
                var x2 = m2.mins.reduce(function (x, y) {
                    return x * (y < 0 ? 2 : 1);
                }, -1);
                return x1 - x2;
            });

            var _loop2 = function _loop2(i) {
                var p = vecList[i];

                var _loop3 = function _loop3(_j2) {
                    var finalJ = _j2;
                    //f1作为判断是否覆盖完毕的标志
                    var f1 = Array.from({ length: var_count }, function (_, index) {
                        return index;
                    }).some(function (x) {
                        return !(p.mins[x] == -1 || p.mins[x] == minterms.get(finalJ).mins[x]);
                    });
                    if (!f1) {
                        pic[i][_j2] = 1;
                        c1[_j2]++;
                        p.num++;
                    }
                };

                for (var _j2 = 0; _j2 < minterms.size(); _j2++) {
                    _loop3(_j2);
                }
            };

            for (var i = 0; i < vec.size(); i++) {
                _loop2(i);
            }

            // console.info("At 152:");
            // console.info(vecList);
            // console.info((pic));
            // console.info((c1));

            //找寻本质本原蕴含项
            for (var j = 0; j < minterms.size(); j++) {
                if (c1[j] == 1) {
                    c1[j] = 0;
                    for (var i = 0; i < vec.size(); i++) {
                        var _p2 = vecList[i];
                        if (pic[i][j] == 1) {
                            _p2.flag1 = 1;
                            pic[i][j] = 0;
                            for (var x = 0; x < minterms.size(); x++) {
                                if (pic[i][x] == 1) {
                                    c1[x] = 0;
                                    for (var l = 0; l < vec.size(); l++) {
                                        var q = vecList[l];
                                        if (pic[l][x] == 1) q.num--;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // console.info("At 180:");
            // console.info(vecList);
            // console.info((pic));
            // console.info((c1));


            /*p=vec->head;
            while(p!=null)
            {
                cout<<p->flag1<<" "<<p->num<<endl;
                p=p->next;
              }*/
            //寻找其它非本质本原蕴含项使得到最小覆盖
            //        p=vec->head;
            //        while(1)
            //        {
            //            int Max=0,pos=0,k=0;
            //            f1=true;
            //            Minterm *q=p;
            //            if(p==null) break;
            //            for(int i=0;i<count;i++)
            //            {if(c1[i]>0) f1=false;}
            //            if(f1==true) break;
            //            while(p!=null)           //找到同时覆盖最多未被覆盖最小项的本原蕴含项q
            //            {
            //
            //                if(p->flag1==1)
            //                {
            //                    if(p->next!=null)
            //                    {p=p->next;k++;continue;}
            //                    else break;
            //                }
            //                else if(p->num>Max) {Max=p->num;q=p;pos=k;}
            //                if(p->next!=null) p=p->next;
            //                else break;
            //                k++;
            //            }
            //            q->flag1=1;		//q所指的蕴含项标记为1表示已被选出
            //            p=vec->head;
            //            for(int i=0;i<count;i++)
            //            {	if(pic[pos][i]==1)	//找到q所指的蕴含项所能表示的最小项
            //            {
            //                c1[i]=0;		//置最小项被表示次数为0，表示已解决
            //                for(int j=0;j<vec->count;j++)
            //                {
            //                    if(pic[j][i]==1) {pic[j][i]=0;p->num--;}
            //                    //根据这些新解决的数调整蕴含项能表示的最小项的个数
            //                    if(p->next!=null) p=p->next;
            //                    else break;
            //                }
            //            }
            //            }
            //
            //        }

            // console.info("最小覆盖：");
            // for (let p of vecList) {
            //     if(p.flag1==1) {
            //         for(let x=0;x<var_count;x++) {
            //             if(p.mins[x]==-1){
            //                 console.info('_');
            //             } else {
            //                 console.info(p.mins[x]);
            //             }
            //         }
            //     }
            // }
            return vec.filter(function (m) {
                return m.flag1 == 1;
            });
        }
    }]);

    return Minterm;
}();

if (Array.prototype.add == undefined) {
    Array.prototype.add = function (e) {
        this.push(e);
    };
}

if (Array.prototype.size == undefined) {
    Array.prototype.size = function (e) {
        return this.length;
    };
}

if (Array.prototype.get == undefined) {
    Array.prototype.get = function (index) {
        return this[index];
    };
}

if (Array.prototype.toArray == undefined) {
    Array.prototype.toArray = function (index) {
        return this;
    };
}
